package me.jiatao.wan.data.repository

import androidx.paging.*
import androidx.room.withTransaction
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import me.jiatao.wan.data.database.AppDataBase
import me.jiatao.wan.data.database.entity.ArticleType
import me.jiatao.wan.data.mapper.ArticleMapper
import me.jiatao.wan.data.mapper.BannerMapper
import me.jiatao.wan.data.network.ApiException
import me.jiatao.wan.data.network.HttpStatusResult
import me.jiatao.wan.data.network.api.WanAndroidApi
import me.jiatao.wan.data.network.apiDataCall
import me.jiatao.wan.data.network.pojo.BannerPojo
import me.jiatao.wan.data.network.pojo.CategoryTreePojo
import me.jiatao.wan.data.network.pojo.NavTreePojo
import me.jiatao.wan.data.network.pojo.UserLoginPojo
import me.jiatao.wan.model.ArticleModel
import me.jiatao.wan.paging3.home.ArticleRemoteMediator
import me.jiatao.wan.paging3.home.HomeArticlePagingSource

/**
 * @Author: taojia
 * @CreateDate: 2021/8/24 5:11 下午
 * @Version: 1.0
 * @Description:
 */

class RepositoryImpl(
    private val api: WanAndroidApi,
    private val db: AppDataBase,
    private val pageConfig: PagingConfig
) : Repository {

    /**
     * 获取首页banner列表
     */
    override fun fetchBannerList(): Flow<HttpStatusResult<List<BannerPojo>>> {

        return flow {
            try {
                val res = apiDataCall {
                    api.fetchBannerListApi()
                }

                /** 更新本地数据 */
                db.withTransaction {
                    db.bannerDao().clear()
                    db.bannerDao().insertList(
                        res.map(BannerMapper::bannerPojo2Entity)
                    )
                }
                emit(HttpStatusResult.Success(res))
                return@flow
            } catch (ex: ApiException) {

                /** 无网络加载本地数据 */
                val bannerList = db.bannerDao().getList().map(BannerMapper::bannerEntity2Pojo)
                if (bannerList.isEmpty()) {
                    emit(HttpStatusResult.Failure(ex))
                } else {
                    emit(HttpStatusResult.Success(bannerList))
                }
            }

        }.flowOn(Dispatchers.IO)
    }

    /**
     * 首页文章列表
     */
    @ExperimentalPagingApi
    override fun fetchHomeArticleList(): Flow<PagingData<ArticleModel>> {
        /** 使用PagingSource */
//        return Pager(
//            config = pageConfig,
//            pagingSourceFactory = {
//                HomeArticlePagingSource(api, ArticleType.HOME)
//            }
//        ).flow.map { pagingData ->
//            pagingData.map {
//                ArticleMapper.articlePojo2Model(it)
//            }
//        }

        /** 使用RemoteMediator */
        return Pager(
            config = pageConfig,
            remoteMediator = ArticleRemoteMediator(api, db, ArticleType.HOME),
            pagingSourceFactory = {
                db.articleDao().getArticlePaging(ArticleType.HOME)
            },
        ).flow.map { pagingData ->
            pagingData.map {
                ArticleMapper.articleEntity2Model(it)
            }
        }
    }

    /**
     * 获取类别列表
     */
    override fun fetchProjectTree(): Flow<HttpStatusResult<List<CategoryTreePojo>>> {
        return flow {
            try {
                val res = apiDataCall {
                    api.fetchProjectTreeApi()
                }

                emit(HttpStatusResult.Success(res))
            } catch (ex: ApiException) {
                emit(HttpStatusResult.Failure(ex))
            }
        }
    }

    /**
     * 获取项目模块文章列表
     */
    override fun fetchProjectArticleList(cid: Int): Flow<PagingData<ArticleModel>> {
        /** 使用RemoteMediator */
        return Pager(
            config = pageConfig,
            pagingSourceFactory = {
                HomeArticlePagingSource(api, ArticleType.PROJECT, cid)
            }
        ).flow.map { pagingData ->
            pagingData.map {
                ArticleMapper.articlePojo2Model(it)
            }
        }
    }

    /**
     * 获取体系列表
     */
    override fun fetchCategoryTree(): Flow<HttpStatusResult<List<CategoryTreePojo>>> {
        return flow {
            try {
                val res = apiDataCall {
                    api.fetchCategoryTreeApi()
                }

                emit(HttpStatusResult.Success(res))
            } catch (ex: ApiException) {
                emit(HttpStatusResult.Failure(ex))
            }
        }
    }

    /**
     * 获取常用网址
     */
    override fun fetchNavTree(): Flow<HttpStatusResult<List<NavTreePojo>>> {
        return flow {
            try {
                val res = apiDataCall {
                    api.fetchNavTreeApi()
                }

                emit(HttpStatusResult.Success(res))
            } catch (ex: ApiException) {
                emit(HttpStatusResult.Failure(ex))
            }
        }
    }

    /**
     * 用户登录
     */
    override fun postUserLogin(userName: String, userPwd: String): Flow<HttpStatusResult<UserLoginPojo>> {
        return flow {
            try {
                val res = apiDataCall {
                    api.postUserLogin(userName, userPwd)
                }

                emit(HttpStatusResult.Success(res))
            } catch (ex: ApiException) {
                emit(HttpStatusResult.Failure(ex))
            }
        }
    }
}